package com.zhizhi.handle;

import com.zhizhi.common.anno.ControllerLog;
import com.zhizhi.domain.RequestTokenBO;
import com.zhizhi.util.RequestTokenUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * [  操作日志记录处理,对所有ControllerLog注解的Controller进行操作日志监控 ]
 * 日志环绕通知
 */
@Aspect
@Component
public class WebLogAspect {

    private Logger logger = LoggerFactory.getLogger(this.getClass());


    /**
     * 获取@controllerLog 注解上信息
     *
     * @param joinPoint
     * @return map
     * @throws Exception
     */
    public static Map<String, Object> getControllerAnnotationValue(JoinPoint joinPoint) throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        Map<String, Object> map = new HashMap<>();
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] classes = method.getParameterTypes();
                if (classes.length == arguments.length) {
                    //取入参数据
                    String description = method.getAnnotation(ControllerLog.class).value();
                    String module = method.getAnnotation(ControllerLog.class).module().getText();
                    map.put("module", module);
                    map.put("operate", description);
                    break;
                }
            }
        }
        return map;
    }

    /**
     * 定义一个切入点.
     * ("execution(public * com.kfit.*.web..*.*(..))")
     * 解释下：
     * 第一个 * 代表任意修饰符及任意返回值.
     * 第二个 * 任意包名
     * 第三个 * 代表任意方法.
     * 第四个 * 定义在web包或者子包
     * 第五个 * 任意方法
     * .. 匹配任意数量的参数.
     */
    @Pointcut("@annotation(com.zhizhi.common.anno.ControllerLog)")
    public void webLog() {
    }

    @Around("webLog()")
    public Object round(ProceedingJoinPoint joinPoint) throws Throwable {
        logger.info("环绕通知开始........");
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //入参  value
        Object[] args = joinPoint.getArgs();
        //入参名称
        String url = request.getRequestURI();

        Object returnValue = joinPoint.proceed();

        Map<String, String[]> paramNames = request.getParameterMap();
        Map<String, Object> values = getControllerAnnotationValue(joinPoint);
        String module = values.get("module").toString();
        String operate = values.get("operate").toString();
        //切面返回值
        // 一切正常的情况下，继续执行被拦截的方法
        RequestTokenBO requestTokenBO = RequestTokenUtil.getRequestAccount();
        String ip = request.getHeader("X-real-ip");
        //记录日志
//        String loginTime = DateUtil.getDateToStr(new Date(), "yyyy-MM-dd");
//        String userId = ExecutionContext.getUserId();
        logger.info("returnValuereturnValuereturnValue........" + returnValue);
        return returnValue;
    }

    @AfterReturning("webLog()")
    public void doAfterReturning(JoinPoint joinPoint) {
        // 处理完请求，返回内容
        logger.info("WebLogAspect.doAfterReturning()");
    }

}